﻿using System;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using System.Globalization;

namespace ExtensionsMadeEasy.Utilities.ValueConverters
{
    [Export(typeof(IMethaphonicStringValueConverter))]
    internal sealed class DutchMethaphoneStringConverter : IMethaphonicStringValueConverter
    {
        public bool CanConvert(string s)
        {
            return new CultureInfo("nl-NL").Equals(System.Threading.Thread.CurrentThread.CurrentUICulture);
        }

        public string Convert(string value)
        {
            return MakeMethaphonicDefault(value);
        }
        internal static string MakeMethaphonicDefault(string original)
        {
            //Based on:
            //http://blogs.u2u.be/diederik/post/2011/02/10/Fuzzy-lookup-of-Names-with-a-Dutch-Metaphone-implementation.aspx            
            StringBuilder sb = new StringBuilder();
            string searchString = original.ToLower();
            for (int i = 0; i < searchString.Length; i++)
            {
                char previousChar = i == 0 ? ' ' : searchString[i - 1];
                char currentChar = searchString[i];
                char nextChar = i == searchString.Length - 1 ? ' ' : searchString[i + 1];
                char nextNextChar = i < searchString.Length - 2 ? searchString[i + 2] : ' ';
                switch (currentChar)
                {
                    case 'a':
                    case 'e':
                    case 'i':
                    case 'o':
                    case 'u':
                        break;
                    case 'b':
                        if (i == searchString.Length - 1)
                            sb.Append('p');
                        else
                            sb.Append('b');
                        break;
                    case 'c':
                        if (nextChar == 'h')
                            if (i == 0)
                                sb.Append('x');
                            else
                                sb.Append('g');
                        else
                            if (previousChar != 's' && (nextChar == 'i' || nextChar == 'e' || nextChar == 'y'))
                                sb.Append('s');
                            else
                                sb.Append('k');
                        break;
                    case 'd':
                        if (nextChar == 'g' && "eyi".Contains(nextNextChar))
                            sb.Append('j');
                        else if (i == searchString.Length - 1)
                            sb.Append('t');
                        else
                            sb.Append('d');
                        break;
                    case 'h':
                        if (!"csptg".Contains(previousChar) && "aeiouy".Contains(nextChar))
                            sb.Append('h');
                        break;
                    case 'j':
                        if (!"is".Contains(previousChar))
                            if (previousChar == 't')
                                sb.Append('x');
                            else
                                sb.Append('j');
                        break;
                    case 'k':
                        if (previousChar != 'c')
                            sb.Append('k');
                        break;
                    case 'p':
                        if (nextChar == 'h')
                            sb.Append('f');
                        else
                            sb.Append('p');
                        break;
                    case 's':
                        if ("hj".Contains(nextChar))
                            sb.Append('x');
                        else
                            sb.Append('s');
                        break;
                    case 't':
                        if (nextChar == 'i' && "aoeu".Contains(nextNextChar))
                            sb.Append('s');
                        else
                            sb.Append('t');
                        break;
                    case 'w':
                        if (nextChar == 'r')
                            sb.Append('v');
                        else
                            sb.Append('w');
                        break;

                    case 'y':
                        if ("aeiou".Contains(nextChar))
                            sb.Append('j');
                        break;

                    default:
                        sb.Append(currentChar);
                        break;
                }
            }
            return sb.ToString().ToUpper();

        }
    }

}
